#pragma once

#include <sys/stat.h>
#include <sys/types.h>
#include <json/json.h>
#include <ctime>
#include <fstream>
#include <filesystem>
#include <iostream>

using std::cout;
using std::endl;

namespace utils
{
    class Date
    {
    public:
        static time_t Now() { return time(nullptr); }
    };


    class File
    {
    public:
        // 检查文件是否存在
        static bool Exists(const std::string &filename)
        {
            return std::filesystem::exists(filename);
        }

        // 获取文件路径
        static const std::string Path(const std::string &filename) 
        {
            if (filename.empty())
                return "";
            return std::filesystem::path(filename).parent_path().string();
        }

        // 创建目录
        static void CreateDirectory(const std::string &pathname) 
        {
            if (pathname.empty())
            {
                std::cerr << "文件所给路径为空：" << std::endl;
                return;
            }
            // 文件不存在再创建
            if (!Exists(pathname))
            {
                std::filesystem::create_directories(pathname);
            }
        }

        // 获取文件大小
        int64_t FileSize(const std::string &filename)
        {
            if (!Exists(filename))
            {
                std::cerr << "Get file size failed: file does not exist" << std::endl;
                return -1;
            }
            return std::filesystem::file_size(filename);
        }

        // 获取文件内容
        bool GetContent(std::string *content, const std::string &filename)
        {
            if (!Exists(filename))
            {
                std::cerr << "file open error: file does not exist" << std::endl;
                return false;
            }

            // 打开文件
            std::ifstream ifs(filename, std::ios::binary);
            if (!ifs.is_open())
            {
                std::cerr << "file open error" << std::endl;
                return false;
            }

            // 读取文件内容
            ifs.seekg(0, std::ios::end);
            size_t len = ifs.tellg();
            ifs.seekg(0, std::ios::beg);
            content->resize(len);
            ifs.read(&(*content)[0], len);
            if (!ifs)
            {
                std::cerr << __FILE__ << ":" << __LINE__ << " - read file content error" << std::endl;
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }
    }; // class File



    class JsonUtil
    {
    public:
        static bool Serialize(const Json::Value &val, std::string& str)
        {
            // 建造者生成->建造者实例化json写对象->调用写对象中的接口进行序列化写入str
            Json::StreamWriterBuilder streamwriterbuilder;
            std::unique_ptr<Json::StreamWriter> usw(streamwriterbuilder.newStreamWriter());

            std::stringstream streamstr;
            if (usw->write(val, &streamstr) != 0)
            {
                std::cout << "serialize error" << std::endl;
                return false;
            }

            str = streamstr.str();
            return true;
        }

        static bool UnSerialize(const std::string &str, Json::Value *val)
        {
            // 操作方法类似序列化
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> ucr(crb.newCharReader());
            std::string err;
            if (ucr->parse(str.c_str(), str.c_str() + str.size(), val, &err) == false)
            {
                std::cout <<__FILE__<<__LINE__<<"parse error" << err<<std::endl;
                return false;
            }
            return false;
        }
    };

    struct JsonData
    {
        static JsonData& GetInstance()
        {
           static JsonData json_data;
           return json_data;
        }
    private:
        JsonData()
        {
            std::string content;
            File file;
            if (!file.GetContent(&content, "/home/su/cloudshare/example/config/config.conf"))
            {
                std::cout << __FILE__ << __LINE__ << "open config.conf failed" << std::endl;
                perror(NULL);
            }

            Json::Value root;
            JsonUtil::UnSerialize(content, &root); // 反序列化，把内容转成jaon value格式
            buffer_size = root["buffer_size"].asInt64();
            threshold = root["threshold"].asInt64();
            linear_growth = root["linear_growth"].asInt64();
            flush_log = root["flush_log"].asInt64();
            backup_addr = root["backup_addr"].asString();
            backup_port = root["backup_port"].asInt();
            thread_count = root["thread_count"].asInt();
        }
            
        public:
            size_t buffer_size;         //缓冲区基础容量
            size_t threshold;           // 倍数扩容阈值
            size_t linear_growth;       // 线性增长容量
            size_t flush_log;           //控制日志同步到磁盘的时机，默认为0,1调用fflush，2调用fsync
            std::string backup_addr;
            uint16_t backup_port;
            size_t thread_count;
    };
}